package net.cmkj.mine.core.admin.calculate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import net.cmkj.mine.bean.Calculate;
import net.cmkj.mine.bean.Columns;
import net.cmkj.mine.common.model.DataGridModel;
import net.cmkj.mine.common.model.InvokeResult;
import net.cmkj.mine.util.CalculateUtil;
import net.cmkj.mine.util.DataGridModelUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class CalculateService {

    private static Logger log = LogManager.getLogger(CalculateService.class);
    private Calculate dao = Calculate.dao;

    /**
     * 获取计算公式列表
     * @param pageNumber
     * @param pageSize
     * @param moduleid
     * @return
     * @throws Exception
     */
    public DataGridModel getList(int pageNumber, int pageSize, long moduleid) throws Exception {
        log.info("获取计算公式列表");
        Page<Calculate> pageInfo = dao.getList(pageNumber, pageSize, moduleid);
        DataGridModel result = DataGridModelUtils.toDataGridView(pageInfo);
        return result;
    }

    /**
     * 获取计算公式列表
     * @param moduleid
     * @return
     * @throws Exception
     */
    public List<Calculate> getList(long moduleid) throws Exception {
        return dao.getList(moduleid);
    }

    /**
     * 获取计算公式
     * @param id
     * @return
     * @throws Exception
     */
    public Calculate findById(Long id) throws Exception {
        return dao.findById(id);
    }

    /**
     * 计算公式保存
     * @param cal
     * @return
     * @throws Exception
     */
    public InvokeResult save(Calculate cal) throws Exception {
        log.info("计算公式保存");
        if (dao.save(cal)) {
            return InvokeResult.success();
        } else {
            return InvokeResult.failure("计算公式保存失败");
        }
    }

    /**
     * 根据模块id删除计算公式
     * @param moduleid
     * @return
     * @throws Exception
     */
    public InvokeResult deleteByModuleid(Long moduleid) throws Exception {
        if (dao.deleteByModuleid(moduleid)) {
            return InvokeResult.success();
        } else {
            return InvokeResult.failure("根据模块id删除计算公式失败");
        }
    }

    /**
     * 删除计算公式
     * @param id
     * @return
     * @throws Exception
     */
    public InvokeResult delete(Long id) throws Exception {
        if (dao.findById(id).delete()) {
            return InvokeResult.success();
        } else {
            return InvokeResult.failure("删除计算公式失败！");
        }
    }

    /**
     * 获取可参与计算公式字段列表
     * @param moduleid
     * @return
     * @throws Exception
     */
    public List<Record> getCalColumnList(Long moduleid) throws Exception {
        return dao.getCalColumnList(moduleid);
    }

    /**
     * 获取被参与计算公式字段列表
     * @param moduleid
     * @param columnid
     * @return
     * @throws Exception
     */
    public DataGridModel getCaledColumnList(Long moduleid, Long columnid) throws Exception {
        List<Columns> list = dao.getCaledColumnList(moduleid, columnid);
        DataGridModel result = new DataGridModel();
        result.setData(list);
        result.setCount(list.size());
        return result;
    }

    /**
     * 根据计算公式计算结果
     * @param formula
     * @param mapstr
     * @return
     * @throws Exception
     */
    public BigDecimal calculate(String formula, String mapstr) throws Exception {
        if (StrKit.notBlank(formula) && StrKit.notBlank(mapstr)) {
            Map<String, Object> variables = new HashMap<>();
            JSONObject object = JSON.parseObject(mapstr);
            Iterator it = object.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry<String, Object>) it.next();
                variables.put(entry.getKey(), entry.getValue());
            }
            BigDecimal result = CalculateUtil.calculate(formula, variables);
            return result;
        } else {
            return new BigDecimal(0);
        }
    }

}
